package com.syq.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.syq.enums.InterfaceExceptionEnums;
import com.syq.exception.SmsException;
import com.syq.model.StandardReport;
import com.syq.model.StandardSubmit;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName: ElkServiceImpl
 * @Description: TODO
 * @Create by: syq
 * @Date: 2022/8/30 8:16
 */

@Slf4j
@Service
public class ElkServiceImpl implements ElkService{

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private ObjectMapper objectMapper;

    @Value("${log-index}")
    private String index;

    @Override
    public void saveLog(StandardSubmit standardSubmit) throws Exception {
        String indexName=index+new SimpleDateFormat("yyyy").format(new Date());
        IndexRequest request=new IndexRequest();
        request.index(indexName);
        request.id(standardSubmit.getSequenceId());
        request.source(objectMapper.writeValueAsString(standardSubmit), XContentType.JSON);
        IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        String result = response.getResult().toString();
        if(!result.equalsIgnoreCase("created")){
            log.error("【搜索模块】添加日志 ， 添加日志失败！！ result = {},submit = {}",response.getResult().toString(),standardSubmit);
            throw new SmsException(InterfaceExceptionEnums.SEARCH_SAVE_LOG_ERROR);
        }
    }

    @Override
    public void updateLog(StandardReport standardReport) throws Exception {
        String indexName=index+new SimpleDateFormat("yyyy").format(new Date());
        UpdateRequest request=new UpdateRequest();
        request.index(indexName);
        request.id(standardReport.getSequenceId());
        Map<String,Object> map=new HashMap<>();
        map.put("reportState",standardReport.getState());
        map.put("errorCode",standardReport.getErrorCode());
        request.doc(map);
        UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        String result = response.getResult().toString();
        if(!result.equalsIgnoreCase("updated")){
            log.error("【搜索模块】修改日志 ， 修改日志失败！！ result = {},submit = {}",response.getResult().toString(),standardReport);
            throw new SmsException(InterfaceExceptionEnums.SEARCH_SAVE_LOG_ERROR);
        }
    }

    @Override
    public List<Map> searchlog(Map map) throws Exception {
        SearchResponse response = getResource(map);
        SearchHit[] hits = response.getHits().getHits();
        List<Map> data=new ArrayList<>();
        for (SearchHit hit : hits) {
            Map<String, Object> source = hit.getSourceAsMap();
            HighlightField messageContent = hit.getHighlightFields().get("messageContent");
            if (!StringUtils.isEmpty(messageContent)){
                String message= messageContent.fragments()[0].string();
                source.put("messageContent",message);
            }
            data.add(source);
        }
        return data;
    }

    @Override
    public Long searchAll(Map map) throws Exception {
        SearchResponse response = getResource(map);
        return response.getHits().getTotalHits().value;
    }

    @Override
    public Map<String, Long> searchStatus(Map map) throws IOException {
        String indexName=index+new SimpleDateFormat("yyyy").format(new Date());
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices(indexName);
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery();
        Integer clientID = (Integer) map.get("clientID");
        if (!StringUtils.isEmpty(clientID)){
            boolQueryBuilder.must(QueryBuilders.termQuery("clientID",clientID));
        }
        Long startTime = (Long) map.get("startTime");
        Long endTime = (Long) map.get("endTime");
        RangeQueryBuilder rangeQueryBuilder=QueryBuilders.rangeQuery("sendZTime");
        if (startTime!=null){
            rangeQueryBuilder.gte(startTime);
        }
        if (endTime!=null){
            rangeQueryBuilder.lte(startTime);
        }
        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.size(10000);
        searchRequest.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = response.getHits().getHits();
        Map<String, Long> data=new HashMap<>();
        long count0=1;
        long count1=1;
        long count2=1;
        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            Integer reportState = (Integer) sourceAsMap.get("reportState");
            if (reportState==0){
                data.put("0",count0);
                count0++;
            }else
            if (reportState==1){
                data.put("1",count1);
                count1++;
            }else {
                data.put("2", count2);
                count2++;
            }
        }
        return data;
    }

    public SearchResponse getResource(Map map) throws Exception {
        String indexName=index+new SimpleDateFormat("yyyy").format(new Date());
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices(indexName);
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery();
        Integer clientID = (Integer) map.get("clientID");
        if (!StringUtils.isEmpty(clientID)){
            boolQueryBuilder.must(QueryBuilders.termQuery("clientID",clientID));
        }
        String mobile = (String) map.get("mobile");
        if (!StringUtils.isEmpty(mobile)){
            boolQueryBuilder.must(QueryBuilders.termQuery("destMobile",mobile));
        }
        String keyword = (String) map.get("keyword");
        if (!StringUtils.isEmpty(keyword)){
            boolQueryBuilder.must(QueryBuilders.matchQuery("messageContent",keyword));
        }
        Long startTime = (Long) map.get("startTime");
        Long endTime = (Long) map.get("endTime");
        RangeQueryBuilder rangeQueryBuilder=QueryBuilders.rangeQuery("sendTime");
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd");
        if (startTime!=null||endTime!=null) {
            if (startTime != null) {
                rangeQueryBuilder.gte(sdf.format(new Date(startTime))).format("yyyy/MM/dd");
            }
            if (endTime != null) {
                rangeQueryBuilder.lte(sdf.format(new Date(endTime))).format("yyyy/MM/dd");
            }
            boolQueryBuilder.must(rangeQueryBuilder);
        }
        //设置分页信息
        Integer start = (Integer) map.get("start");
        Integer size = (Integer) map.get("rows");
        sourceBuilder.from(start);
        sourceBuilder.size(size);
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("messageContent");
        highlightBuilder.preTags((String) map.get("highLightPreTag"));
        highlightBuilder.postTags((String) map.get("highLightPostTag"));
        sourceBuilder.highlighter(highlightBuilder);
        sourceBuilder.query(boolQueryBuilder);
        searchRequest.source(sourceBuilder);
        System.out.println(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        return response;
    }
}
